[Arduino Uno] ArduinoSTLでC++のSTLのようなものを使う
こんにちは、CX事業本部のうらわです。
最近Arduino(Arduino Uno Rev3 ATmega328)を購入し、Neovim/C++/Arduino CLIでお試し中です。
あまりArduinoの開発事情を知らずにC++で進めていますが、さっそく標準ライブラリは使えないけどどうすれば良いの、という問題にぶつかりました。初歩的かもしれませんがどう対応したかをご紹介します。
作業環境
- Mac/NeoVim/C++/Arduino CLIで作業しています。Arduino IDEは使用していません。NeoVimではclangdを導入して補完や定義へ移動が効くようにしています。
-
arduino-cli
コマンド実行時には--config-file
オプションで設定ファイルarduino-cli.yaml
を指定します。これは、デフォルトの設定ファイルやライブラリの保存先($HOME/Library/Arduino15
)から任意のディレクトリに変えるために指定しています。
# 例 $ arduino-cli board list --config-file ~/.arduino15/arduino-cli.yaml
上記の2点について、詳細は前回の記事をご参照ください。
ArduinoSTLのインストール
Arduino UnoではArduinoSTLというライブラリをインストールすることでC++の標準ライブラリのようなものを使うことできるようです。このライブラリを使わず<vector>
などをインクルードしてもエラーになります。
ArduinoSTL
のインストールはArduino CLIでできます。
# ライブラリを探す $ arduino-cli lib search ArduinoSTL Updating index: library_index.json downloaded Name: "ArduinoSTL" Author: Mike Matera <matera@lifealgorithmic.com> Maintainer: Mike Matera <matera@lifealgorithmic.com> Sentence: A port of uClibc++ packaged as an Arduino library. Paragraph: This library includes important C++ functions, including cout and cin, printf and scanf. It also includes STL containers like vector and algorithm. Website: https://github.com/mike-matera/ArduinoSTL Category: Other Architecture: avr, samd Types: Contributed Versions: [0.1.1, 0.1.2, 0.1.4, 0.1.5, 0.1.6, 0.1.7, 0.1.8, 1.0.2, 1.0.4, 1.0.5, 1.1.0] Provides includes: ArduinoSTL.h // ...省略... # インストール $ arduino-cli lib install ArduinoSTL --config-file ~/.arduino15/arduino-cli.yaml Downloading ArduinoSTL@1.1.0... ArduinoSTL@1.1.0 downloaded Installing ArduinoSTL@1.1.0... Installed ArduinoSTL@1.1.0
compile_flags.txt
にインストールしたArduinoSTL
のヘッダーファイルの場所を記載しておきます。これでclangdによる補完等が機能します。
-I/path/to/.arduino15/libraries/ArduinoSTL/src
実装・コンパイルする
準備ができたので、std::vector
とstd::sort
を使う適当なC++ファイルを作成します。
#include <Arduino.h> #include <ArduinoSTL.h> std::vector<String> v; void setup() { Serial.begin(9600); for (int i = 0; i < 10; i++) { v.push_back(String("hello!") + String(i)); } } void loop() { std::sort(v.begin(), v.end()); for(int i = 0; i < 10; i++) { Serial.println(v[i]); delay(2000); } }
コンパイルするとArduinoSTL
関連で以下のエラーが出てしまいました。
$ arduino-cli compile --fqbn arduino:avr:uno DummySketch --config-file ~/.arduino15/arduino-cli.yaml /path/to/.arduino15/libraries/ArduinoSTL/src/d el_opnt.cpp:25:56: error: 'nothrow_t' in namespace 'std' does not name a type _UCXXEXPORT void operator delete(void* ptr, const std::nothrow_t& ) throw() { ^~~~~~~~~ /path/to/.arduino15/libraries/ArduinoSTL/src/d el_opvnt.cpp:25:58: error: 'nothrow_t' in namespace 'std' does not name a type _UCXXEXPORT void operator delete[](void* ptr, const std::nothrow_t& ) throw(){ ^~~~~~~~~ /path/to/.arduino15/libraries/ArduinoSTL/src/d el_opvs.cpp:25:53: error: 'std::size_t' has not been declared _UCXXEXPORT void operator delete[](void * ptr, std::size_t) throw(){ ^~~~~~ /path/to/.arduino15/libraries/ArduinoSTL/src/d el_ops.cpp:25:50: error: 'std::size_t' has not been declared _UCXXEXPORT void operator delete(void* ptr, std::size_t) throw(){
頑張っていろいろ検索したところ、以下のissueにワークアラウンドとしてAVRボードバージョンを最新の1.8.3から1.8.2にダウングレードする、という記載があります。Arduino CLIでバージョンを指定してインストールすることで、コンパイルエラーは消えました。
参考:https://github.com/mike-matera/ArduinoSTL/issues/56#issuecomment-648091795
# 何も指定しないと最新のArduino AVRボードバージョンでインストールされる $ arduino-cli core install arduino:avr --config-file ~/.arduino15/arduino-cli.yaml #バージョンを指定してインスールする $ arduino-cli core install arduino:avr@1.8.2 --config-file ~/.arduino15/arduino-cli.yaml
おわりに
なんとかC++の感覚で実装を進められそうで良かったです。
その他、Arduinoの開発関連でよく使うライブラリは以下の記事がとても参考になりそうです。本記事で使用しているArduinoSTL
と共存して利用可能なC++の標準ライブラリのような挙動をするライブラリについても解説されています。かなり便利そうなので使ってみようと思います。